/*
-----------------
Unicorn Princess
Iteration 1
Rachel J. Morris
www.moosader.com
Dec 2009-Feb 2010
-----------------

CharacterManager.cpp
*/

#include "CharacterManager.h"

// Singleton intialization accessors
CharacterManager& CharacterManager::GetInst()
{
    if ( !inst )
        inst = new CharacterManager();

    return *inst;
}

CharacterManager* CharacterManager::InstPtr()
{
    if ( !inst )
        inst = new CharacterManager();

    return inst;
}

// Initialization / Constructors / Destructors
CharacterManager::CharacterManager()
{
    ;
}

void CharacterManager::Destroy()
{
    if ( inst != NULL )
        delete [] inst;
}

void CharacterManager::Init()
{
    /* Initialize the enemies on level 0 */

    player.Init();
}

int CharacterManager::EnemyCount() { return enemyCount; }

void CharacterManager::EnemyCount( int val ) { enemyCount = val; }

void CharacterManager::CreateEnemy( string& type, int x, int y )
{
    if ( enemy == NULL )
    {
        // Array is currently empty, so allocate space and create enemy

        enemyCount++;
        enemy = new Enemy[enemyCount];

        // Create new enemy
        enemy[enemyCount-1].Init( type, x, y );
    }
    else
    {
        // Array already has one or more element(s).  Resize it and then crate enemy.

        AddOneToEnemyArray();

        // Create new enemy
        enemy[enemyCount-1].Init( type, x, y );
    }
}

void CharacterManager::AddOneToEnemyArray()
{
    // Reallocate space for arrays
    Enemy* tempArray = NULL;
    tempArray = new Enemy[enemyCount];

    for ( int i=0; i<enemyCount; i++ )
    {
        tempArray[i] = enemy[i];
    }

    delete [] enemy;
    enemy = NULL;
    enemyCount++;
    enemy = new Enemy[enemyCount];

    for ( int i=0; i<enemyCount-1; i++ )
    {
        enemy[i] = tempArray[i];
    }

    delete [] tempArray;
    tempArray = NULL;
}

void CharacterManager::DrawCharacters()
{
    for ( int i=0; i<enemyCount; i++ )
    {
        if ( enemy[i].Active() == true )
            enemy[i].Draw();
    }

    if ( player.Active() == true )
        player.Draw();
}

void CharacterManager::UpdateCharacters()
{
    /*
        Fix / clean up plzthx!
    */
    SDL_Rect tempColRegA, tempColRegB;

    for ( int i=0; i<enemyCount; i++ )
    {
        // Check for collisions w/ bullets
        for ( int j=0; j<MAX_BULLETS; j++ )
        {
                // Check enemy collision
                tempColRegA = enemy[i].CollisionCoord();
                tempColRegB = BulletManager::GetInst().bullet[j].CollisionCoord();

                if ( (BulletManager::GetInst().bullet[j].GetBulletDamage() == ENEMY || BulletManager::GetInst().bullet[j].GetBulletDamage() == ALL) &&
                        (IsCollision( tempColRegA, tempColRegB )) )
                {
                    // Bullet and enemy must be active, bullet must be the type that damages the enemy or all, and must be a collision between them.
                    enemy[i].Die();
                    BulletManager::GetInst().bullet[j].Explode();
                }

                tempColRegA = player.CollisionCoord();
                tempColRegB = BulletManager::GetInst().bullet[j].CollisionCoord();

                // Check player collision
                if ( (BulletManager::GetInst().bullet[j].GetBulletDamage() == PLAYER || BulletManager::GetInst().bullet[j].GetBulletDamage() == ALL) &&
                        (IsCollision( tempColRegA, tempColRegB )) )
                {
                    // Bullet and player must be active, bullet must be the type that damages the player or all, and must be a collision between them.
                    player.Die();
                    BulletManager::GetInst().bullet[j].Explode();
                }
        }//for ( int j=0; j<MAX_BULLETS; j++ )
        for ( int j=0; j<enemyCount; j++ )
        {
            // Check collision between all enemies
            if ( i != j )
            {
                tempColRegA = enemy[i].CollisionCoord();
                tempColRegB = enemy[j].CollisionCoord();
                if ( IsCollision( tempColRegA, tempColRegB ) )
                {
                    if ( enemy[i].Y() > enemy[j].Y() )
                    {
                        enemy[i].Move( DOWN );
                        enemy[j].Move( UP );
                    }
                    else
                    {
                        enemy[i].Move( UP );
                        enemy[j].Move( DOWN );
                    }
                }
            }
        }//for ( int j=0; j<enemyCount; j++ )

        // Check player-enemy collision

        tempColRegA = enemy[i].CollisionCoord();
        tempColRegB = player.CollisionCoord();

        if ( IsCollision( tempColRegA, tempColRegB ) )
        {
            enemy[i].Die();
            player.Die();
        }

        enemy[i].Update( player );
    }

    // Check player collision with items
    for ( int i=0; i<ItemManager::GetInst().ItemCount(); i++ )
    {
        tempColRegA = player.CollisionCoord();
        tempColRegB = ItemManager::GetInst().item[i].CollisionCoord();
        if ( IsCollision( tempColRegA, tempColRegB ) )
        {
            player.GetItem( ItemManager::GetInst().item[i].GetItemType() );
            ItemManager::GetInst().item[i].Die();
            SoundManager::GetInst().PlaySound( "Jingle" );
        }
    }

    // I wonder if the enemy should be able to pick up bullet upgrades?  Should they chase after it?

    player.Update();
}
